/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 * Description: model manager Unit Test
 */
#include <gtest/gtest.h>
#include <mockcpp/mockcpp.hpp>
#include <mockcpp/mockable.h>

#include "model_manager/model_manager_ext.h"

using namespace std;
using namespace hiai;

class ModelManagerSharedMemUt : public testing::Test {
public:
    void SetUp()
    {
        builtModel_ = CreateBuiltModel();
        const char* file = "bin/llt/framework/domi/modelmanager/om/tf_softmax_hcs_cpucl.om";
        builtModel_->RestoreFromFile(file);

        modelManagerExt_ = IModelManagerExt::CreateModelManagerExt();
    }

    void TearDown()
    {
        GlobalMockObject::verify();
    }

public:
    ModelInitOptions options_;
    std::shared_ptr<IBuiltModel> builtModel_ {nullptr};
    std::shared_ptr<IModelManagerExt> modelManagerExt_ {nullptr};
    std::shared_ptr<ISharedMemAllocator> memAllocator_ {nullptr};
};

static const int g_dataSize = 1 * 1 * 224 * 224 * sizeof(float);
static const std::vector<NativeHandle> g_handle = {{1, g_dataSize, 0}, {2, g_dataSize, 1}};
static const uint32_t g_config = 0;

void StubAllocator(uint32_t requiredSize, hiai::NativeHandle handles[], uint32_t handlesSize, void* config,
    uint32_t *allocatedHandlesSize)
{
    std::cout << __func__ << std::endl;

    EXPECT_NE(0, requiredSize);
    EXPECT_NE(nullptr, handles);
    EXPECT_EQ(10, handlesSize); /* 10:外部申请内存NativeHandle数量规格 */
    if (config != nullptr) {
        EXPECT_EQ(&g_config, config);
        EXPECT_EQ(g_config, *(uint32_t*)config);
    }

    for (uint32_t i = 0; i < g_handle.size(); i++) {
        handles[i] = g_handle[i];
    }
    *allocatedHandlesSize = g_handle.size();
}

void StubFree(hiai::NativeHandle handles[], uint32_t handlesSize, void* config)
{
    std::cout << __func__ << std::endl;

    EXPECT_EQ(g_handle.size(), handlesSize);
    EXPECT_NE(nullptr, handles);
    for (uint32_t i = 0; i < g_handle.size(); i++) {
        EXPECT_EQ(handles[i].fd, g_handle[i].fd);
        EXPECT_EQ(handles[i].size, g_handle[i].size);
        EXPECT_EQ(handles[i].offset, g_handle[i].offset);
    }

    if (config != nullptr) {
        EXPECT_EQ(&g_config, config);
        EXPECT_EQ(g_config, *(uint32_t*)config);
    }
}

TEST_F(ModelManagerSharedMemUt, Model_Manager_Init_001)
{
    memAllocator_ = ISharedMemAllocator::Create(StubAllocator, StubFree, (void*)&g_config);
    EXPECT_NE(nullptr, memAllocator_);

    EXPECT_EQ(SUCCESS, modelManagerExt_->Init(options_, builtModel_, nullptr, memAllocator_));
}

TEST_F(ModelManagerSharedMemUt, Model_Manager_Init_002)
{
    memAllocator_ = nullptr;
    EXPECT_EQ(FAILURE, modelManagerExt_->Init(options_, builtModel_, nullptr, memAllocator_));
}

TEST_F(ModelManagerSharedMemUt, Model_Manager_Init_003)
{
    memAllocator_ = ISharedMemAllocator::Create(nullptr, StubFree, (void*)&g_config);
    EXPECT_NE(nullptr, memAllocator_);

    EXPECT_EQ(FAILURE, modelManagerExt_->Init(options_, builtModel_, nullptr, memAllocator_));
}

TEST_F(ModelManagerSharedMemUt, Model_Manager_Init_004)
{
    memAllocator_ = ISharedMemAllocator::Create(StubAllocator, nullptr, (void*)&g_config);
    EXPECT_NE(nullptr, memAllocator_);

    EXPECT_EQ(FAILURE, modelManagerExt_->Init(options_, builtModel_, nullptr, memAllocator_));
}

TEST_F(ModelManagerSharedMemUt, Model_Manager_Init_005)
{
    memAllocator_ = ISharedMemAllocator::Create(StubAllocator, StubFree, nullptr);
    EXPECT_NE(nullptr, memAllocator_);

    EXPECT_EQ(SUCCESS, modelManagerExt_->Init(options_, builtModel_, nullptr, memAllocator_));
}
